package com.myspring.aop.eg.annoaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

//切面类
@Component//ioc容器
@Aspect//切面类
public class LogAspect {

    //设置切入点和通知类型
    //切入点表达式：execution(修饰符 返回值类型 包名.类名(全路径).方法名(参数列表))
    //JoinPoint:获得增强方法的信息
    //joinPoint.getSignature()获取目标方法的签名
    //通知类型:
    // 前置通知@Before(value="切入点表达式配置切入点")
    @Before("execution(public int com.myspring.aop.eg.annoaop.CalculatorImpl.add(int, int))")
    //@Before("pointCut()")
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("before method:" + "methodName:" + methodName + "参数" + Arrays.toString(args));
    }

    // 返回通知@AfterReturning
    @AfterReturning(value = "execution(* com.myspring.aop.eg.annoaop.CalculatorImpl.*(..))",returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("AfterReturning method:" + "methodName:" + methodName + "返回结果:" + result);
    }
    // 异常通知@AfterThrowing
    @AfterThrowing(value = "execution(* com.myspring.aop.eg.annoaop.CalculatorImpl.*(..))",throwing = "ex")
    public void AfterReturning(JoinPoint joinPoint, Throwable ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("AfterThrowing method:" + "methodName:" + methodName + "异常信息:" + ex);
    }
    // 后置通知@After
    //@After("com.myspring.aop.eg.annoaop.LogAspect.pointCut()")
    @After("pointCut()")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("after method:" + "methodName:" + methodName);
    }
    // 环绕通知@Around
    @Around("execution(* com.myspring.aop.eg.annoaop.CalculatorImpl.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Around method:" + "methodName:" + methodName + "参数" + Arrays.toString(args));
        Object result = null;
        try{
            System.out.println("环绕通知==目标方法之前执行");

            //调用目标方法
            result = joinPoint.proceed();

            System.out.println("环绕通知==目标方法返回值之后");
        }catch (Throwable ex){
            ex.printStackTrace();
            System.out.println("环绕通知==目标方法出现异常执行");
        }finally {
            System.out.println("环绕通知==目标方法执行完毕");
        }
        return result;
    }
    //重用切入点表达式
    @Pointcut("execution(* com.myspring.aop.eg.annoaop.CalculatorImpl.*(..)))")
    public void pointCut(){

    }
}
